﻿using System;
using System.IO;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace StemServiceWebRole
{
    /// <summary>
    /// Interacts with Windows Azure to store / retrieve binary large objects (BLOBs).
    /// </summary>
    public class CloudHandler
    {
        /// <summary>
        /// Initializes a new instance of CloudHandler.
        /// </summary>
        public CloudHandler()
        {
#if(DEBUG)
            // in debug mode use local azure storage emulator
            account = CloudStorageAccount.Parse("UseDevelopmentStorage=true");
#else
            // in release mode use real azure account
            account = CloudStorageAccount.Parse("AccountName=stem123l;AccountKey=YxjDlDV2k6dXRQ4S7IWqBIP61jAggCv0CJczrfYcDAkuEwtRUIGO6O40ZkJy1Yl//A6fcHNBG/TtxerOa8jePA==;DefaultEndpointsProtocol=https");
#endif
        }

        /// <summary>
        /// Adds content to cloud storage.
        /// </summary>
        /// <param name="presentationId">Id of presentation.</param>
        /// <param name="contentType">Type of content.</param>
        /// <param name="content">Array of bytes representing content.</param>
        /// <param name="contentVersion">Version of content.</param>
        /// <returns>Uri of content uploaded in cloud.</returns>
        public Uri AddContent(uint presentationId, ContentTypes contentType, byte[] content, uint contentVersion)
        {
            string contentName = Guid.NewGuid().ToString();
            Uri contentUri = null;
            string mimeType = string.Empty;

            // set mimetype and name of file
            switch (contentType)
            {
                case ContentTypes.JPEG:
                    mimeType = "image/jpeg";
                    contentName = contentName + ".jpg";
                    break;
                case ContentTypes.MP4:
                    mimeType = "video/mp4";
                    contentName = contentName + ".mp4";
                    break;
                case ContentTypes.WAV:
                    mimeType = "audio/x-wav";
                    contentName = contentName + ".wav";
                    break;
                default:
                    throw new ArgumentException("Unsupported content type.");
            }

            using (Stream memStream = new MemoryStream(content))
            {
                CloudBlobClient client = account.CreateCloudBlobClient();

                // get access to blob container
                CloudBlobContainer container = client.GetContainerReference(string.Format(ContainerString, presentationId, contentVersion));
                if (container.CreateIfNotExist())
                {
                    BlobContainerPermissions permissions = new BlobContainerPermissions();
                    permissions.PublicAccess = BlobContainerPublicAccessType.Blob;
                    container.SetPermissions(permissions);
                }

                // get access to blob
                CloudBlob blob = container.GetBlobReference(contentName);
                blob.Properties.ContentType = mimeType;

                // upload stream and retrieve url
                memStream.Seek(0, SeekOrigin.Begin);
                blob.UploadFromStream(memStream);
                contentUri = blob.Uri;
            }

            return contentUri;
        }

        /// <summary>
        /// Removes specific version of content related to a presentation.
        /// </summary>
        /// <param name="presentationId">Id of presentation.</param>
        /// <param name="contentVersion">Version to be removed.</param>
        public void RemoveContent(uint presentationId, uint contentVersion)
        {
            CloudBlobClient client = account.CreateCloudBlobClient();

            // get access to blob container
            CloudBlobContainer container = client.GetContainerReference(string.Format(ContainerString, presentationId, contentVersion));

            // delete container and all content existing in it
            container.Delete();
        }

        /// <summary>
        /// Account to be used in Windows Azure storage.
        /// </summary>
        private CloudStorageAccount account;

        /// <summary>
        /// Format of string used to create / manage a container.
        /// A container actually stores content related to a presentation.
        /// </summary>
        private const string ContainerString = "stem123-{0}-{1}"; // stem123-id of presentation-version number
    }
}